package com.sykj.seaflow.warm.module.def.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO;
import com.sykj.seaflow.warm.module.def.params.SeaFlowDefinitionPageParam;
import com.sykj.seaflow.warm.module.design.service.SeaFlowDesignService;
import com.warm.flow.core.entity.Definition;
import com.warm.flow.core.service.DefService;
import com.warm.flow.core.utils.page.Page;
import com.warm.flow.orm.entity.FlowDefinition;
import lombok.AllArgsConstructor;
import com.sykj.seaflow.common.base.bean.PageQuery;
import com.sykj.seaflow.warm.module.category.entity.FlowCategory;
import com.sykj.seaflow.warm.module.category.service.FlowCategoryService;
import com.sykj.seaflow.warm.module.def.entity.FlowApproval;
import com.sykj.seaflow.warm.module.def.entity.FlowDefExt;
import com.sykj.seaflow.warm.module.def.entity.SeaFlowDefinition;
import com.sykj.seaflow.warm.module.def.params.SeaFlowDefinitionPageParam;
import com.sykj.seaflow.warm.module.def.service.FlowDefExtService;
import com.sykj.seaflow.warm.module.def.service.FlowDefinitionService;
import com.sykj.seaflow.warm.module.design.entity.SeaFlowDesign;
import com.sykj.seaflow.warm.module.design.params.SeaFlowDesignPageParam;
import com.sykj.seaflow.warm.module.design.service.SeaFlowDesignService;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@AllArgsConstructor
@Service
public class FlowDefinitionServiceImpl implements FlowDefinitionService {
        private final DefService defService;
    private final SeaFlowDesignService designService;
    private final FlowCategoryService categoryService;
    private final FlowDefExtService defExtService;


    @Override
    public IPage<Definition> page(SeaFlowDefinitionPageParam flowDefinitionPageParam, PageQuery<SeaFlowDefinition> pageQuery) {
//        Definition definition = BeanUtil.copyProperties(flowDefinitionPageParam, FlowDefinition.class);
        FlowDefinition flowDefinition = new FlowDefinition();
        if(ObjectUtil.isNotEmpty(flowDefinitionPageParam.getFlowCode())){
            flowDefinition.setFlowCode(flowDefinitionPageParam.getFlowCode());
        }
        if(ObjectUtil.isNotEmpty(flowDefinitionPageParam.getFlowName())){
            flowDefinition.setFlowName(flowDefinitionPageParam.getFlowName());
        }

        Page<Definition> page = new Page<>(pageQuery.getCurrent(), pageQuery.getSize());
        //page 转化
        List<OrderItem> orders = pageQuery.getPage().orders();
        if(ObjectUtil.isNotEmpty(orders)){
            String column = orders.get(0).getColumn();
            page.setOrderBy(column);
            page.setIsAsc(orders.get(0).isAsc()? "asc" :"desc");
        }
        Page<Definition> page1 = defService.page(flowDefinition, page);
        PageDTO<Definition> pageDto = new PageDTO<>(page1.getPageNum(), page1.getPageSize(), page1.getTotal());
        pageDto.setRecords(page1.getList());
        return pageDto;
    }

    @Override
    public List<FlowApproval> list(SeaFlowDefinitionPageParam flowDefinitionPageParam) {
        List<FlowApproval> flowApprovals = new ArrayList<>();
        List<FlowCategory> categories = categoryService.list(Wrappers.<FlowCategory>lambdaQuery().orderByAsc(FlowCategory::getSortNum));
        if(ObjectUtil.isNotEmpty(categories)){
            // 获取设计中的 发布流程
            List<SeaFlowDesign> list = designService.canUseFlow(new SeaFlowDesignPageParam());
            Map<Long, List<SeaFlowDesign>> designGroup = list.stream().collect(Collectors.groupingBy(SeaFlowDesign::getCategoryId));
            // 拿到流程定义id，去查询流程
            List<Long> defIds = list.stream().filter(ObjectUtil::isNotEmpty).map(SeaFlowDesign::getDefId).toList();
            if(ObjectUtil.isNotEmpty(defIds)){
                // 流程定义和 扩展信息
                List<Definition> definitions = defService.getByIds(defIds);
                List<FlowDefExt> flowDefExts = defExtService.listByIds(defIds);
                Map<Long, FlowDefExt> flowDefExtMap = flowDefExts.stream().collect(Collectors.toMap(FlowDefExt::getId, Function.identity()));
                // 提取id
                Map<Long, Definition> defMap = definitions.stream().collect(Collectors.toMap(Definition::getId, Function.identity()));
                // 流程分类
                for(FlowCategory category: categories){
                    // 当前分类下的流程设计
                    List<SeaFlowDesign> SeaFlowDesigns = designGroup.get(category.getId());
                    if(ObjectUtil.isNotEmpty(SeaFlowDesigns)){
                        List<SeaFlowDesign> categoryDefs = SeaFlowDesigns.stream().map(r -> {
                            Definition definition = defMap.get(r.getDefId());
                            // 流程设计表的数据 前端配置会有变动， 而 Definition 发布后数据就不会变了
                            SeaFlowDesign SeaFlowDesign = BeanUtil.copyProperties(definition, SeaFlowDesign.class);
                            FlowDefExt flowDefExt = flowDefExtMap.get(SeaFlowDesign.getId());
                            if(ObjectUtil.isNotNull(flowDefExt)){
                                SeaFlowDesign.setFlowJson(flowDefExt.getFlowJson());
                            }
                            SeaFlowDesign.setFlowVersion(definition.getVersion());
                            SeaFlowDesign.setIcon(r.getIcon());
                            SeaFlowDesign.setSortNum(r.getSortNum());
                            return SeaFlowDesign;
                        }).filter(ObjectUtil::isNotEmpty).toList();
                        FlowApproval flowApproval = new FlowApproval(category, categoryDefs);

                        flowApprovals.add(flowApproval);
                    }else{
                        flowApprovals.add(new FlowApproval(category, new ArrayList<>()));
                    }

                }

            }
        }


        return flowApprovals;
    }

    private void putDef(Map<String, List<Definition>> result, String categoryId, Definition definition) {
        List<Definition> definitions = result.computeIfAbsent(categoryId, k -> new ArrayList<>());
        definitions.add(definition);
    }
}
